/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "节点构建.h"


#include <节点/插座/list/list数值插座.h>
#include <节点/插座/list/list矢量插座.h>
#include <节点/插座/材质纹理插座.h>
#include <节点/插座/字符插座.h>

#include "A_引擎/引擎.h"

#include <字符串/str_分割.h>



static void on_插座参数修改更新节点(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);
	}
	//((C_节点面板*)f_global_get激活节点())->m_NodeData->f_set是否要更新(true);

}


static void on_更新节点_缓存冻结(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);

		f_NT_冻结节点(节点, 节点->m_冻结数据);

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构对象指针)节点面板);
		}
	}
}



static void on_更新节点_数据可视(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_Show(节点->m_显示数据);
		/*for (auto& panel : 节点->m_UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构对象指针)节点面板);
		}*/
	}
}


static void on_更新节点_修改名称(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);
		f_str_去路径空白字符(f_prop_Str(prop));
		f_NT_设置节点名称(节点, f_prop_Str(prop));
	}
}



C_节点面板* f_节点创建_UI面板构建(S_UI创建环境& ctx, C_节点基类* data, E_节点区类型 区类型) {
	C_节点面板* plane = new C_节点面板(data, ctx, 区类型);

	uint16 socketNum = 0;
	socketNum = data->f_get输入插座Num();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输入插座(i);

		plane->f_addInSocket(socket);
	}

	socketNum = data->f_get输出插座Num();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输出插座(i);

		plane->f_addOutSocket(socket);
	}

	return plane;
}







static std::wstring f_插座数值转文本(C_插座基类* socket) {
	std::wstring t = socket->f_getTypeName() + L":";

	switch (socket->m_Type) {
		case E_值类型::e_Type_F32:
			t += f_浮点数值转宽字符串(DEF_F32插座数据(socket));
			break;
		case E_值类型::e_Type_I8:
			t += f_整数值转宽字符串(DEF_I8插座数据(socket));
			break;
		case E_值类型::e_Type_I32:
			t += f_整数值转宽字符串(DEF_I32插座数据(socket));
			break;
		case E_值类型::e_Type_UI32:
			t += f_整数值转宽字符串(DEF_UI32插座数据(socket));
			break;
		case E_值类型::e_Type_Vec3: {
			vec3 v = DEF_Vec3插座数据(socket);
			t += L"(" + f_浮点数值转宽字符串(v.x, 4) + L"," + f_浮点数值转宽字符串(v.y, 4) + L"," + f_浮点数值转宽字符串(v.z, 4) + L")";
			break;
		}
		case E_值类型::e_Type_iVec3: {
			ivec3 v = DEF_iVec3插座数据(socket);
			t += L"(" + f_整数值转宽字符串(v.x) + L"," + f_整数值转宽字符串(v.y) + L"," + f_整数值转宽字符串(v.z) + L")";
			break;
		}

		case E_值类型::e_Type_I8_1D: {
			const auto& val = DEF_I8插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_I32_1D: {
			const auto& val = DEF_I32插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_F32_1D: {
			const auto& val = DEF_F32插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}

		case E_值类型::e_Type_Vec2_1D: {
			const auto& val = DEF_Vec2插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_Vec3_1D: {
			const auto& val = DEF_Vec3插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_iVec3_1D: {
			const auto& val = DEF_iVec3插座_1D数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_Mat4X4_1D: {
			const auto& val = DEF_Mat44插座_1D数据(socket, 0);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}

		case E_值类型::e_Type_材质1D: {
			const auto& val = DEF_材质插座_1D数据(socket, 0);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		case E_值类型::e_Type_纹理1D: {
			const auto& val = DEF_纹理插座_1D数据(socket, 0);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}

		case E_值类型::e_Type_Array: {
			const auto& val = DEF_数组插座数据(socket);
			t += L"(" + f_整数值转宽字符串(val->count) + L")";
			break;
		}
		default:
			//t = socket->f_getTypeName() + L":" + socket->m_identifier;
			break;
	}
	return t;
}






void f_节点重构_面板重构(C_节点面板* plane, C_节点基类* data, E_节点区类型 区类型) {
	plane->m_区 = 区类型;
	plane->m_NodeData = data;
	plane->m_节点当前所在视口 = nullptr;
	
	plane->f_setOriginalPos(data->m_坐标);

	data->m_包含在多个视口的UI部件.insert(plane);
}

void f_节点重构_插座重构(C_节点面板* plane, C_节点基类* data, E_节点区类型 区类型) {
	
	plane->f_releaseAllSocket();


	uint16 socketNum = 0;
	socketNum = data->f_get输入插座Num();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输入插座(i);

		plane->f_addInSocket(socket);
	}

	socketNum = data->f_get输出插座Num();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输出插座(i);

		plane->f_addOutSocket(socket);
	}
}

void f_节点重构_面板插座重构(C_节点面板* plane, C_节点基类* node, E_节点区类型 区类型) {
	f_节点重构_面板重构(plane, node, 区类型);
	f_节点重构_插座重构(plane, node, 区类型);
}

bool f_节点重构_重构属性面板数据(C_节点面板* plane, std::vector<S_Props>& props) {
	C_节点基类* 节点 = dynamic_cast<C_节点基类*>(plane->m_NodeData);
	if(节点->m_越过更新) return false;


	S_Props Prop显示可视 = f_alloc_BoolProp(&(节点->m_显示数据), L"显示数据");
	Prop显示可视.m_私有 = true;
	Prop显示可视.m_UI->m_Update = on_更新节点_数据可视;
	props.push_back(Prop显示可视);

	S_Props Prop冻结 = f_alloc_BoolProp(&(节点->m_冻结数据), L"冻结数据");
	Prop冻结.m_私有 = true;
	Prop冻结.m_UI->m_Update = on_更新节点_缓存冻结;
	props.push_back(Prop冻结);

	节点->m_启用.m_UI->m_Update = on_更新节点_缓存冻结;
	props.push_back(节点->m_启用);

	S_Props Prop节点名称 = f_alloc_LineStrProp(nullptr, L"节点名称");
	Prop节点名称.m_私有 = true;
	Prop节点名称.m_UI->m_Update = on_更新节点_修改名称;
	f_prop_Str(Prop节点名称) = 节点->m_Name;
	props.push_back(Prop节点名称);


	auto 子集树 = 节点->f_get子集树();
	if (子集树) {
		S_Props Prop节点树名称 = f_alloc_LineStrProp(nullptr, L"节点树名称");
		f_prop_Str(Prop节点树名称) = 节点->f_get子集树()->m_IDName;
		props.push_back(Prop节点树名称);
	}
	
	if(节点->m_冻结数据 || 节点->m_越过更新) return false;




	std::vector<S_标题和图标> ico_name;
	uint32 num = 节点->f_get输入插座Num();

	S_Props box;
	{
		uint32 i = 0;
		switch (节点->m_Type) {
		case E_节点类型::e_节点Type_几何:
		case E_节点类型::e_节点Type_函数: {
			auto* tree = 节点->f_get子集树();
			tree->m_编译方式.m_UI->m_Update = on_插座参数修改更新节点;
			props.push_back(tree->m_编译方式);
			//break;
		}
			
		case E_节点类型::e_节点Type_组输出:
		//case E_节点类型::e_节点Type_函数:
		//case E_节点类型::e_节点Type_循环迭代:
		//case E_节点类型::e_节点Type_循环:
			if (节点->m_插座可编辑) {
				box = f_alloc_PropContainer(DEF_输入插座标题);
				++i;
				break;
			}
			
		default:
			box = f_alloc_PropLayout(DEF_输入插座标题, E_值类型::e_Type_LayoutList);
			//box.m_私有 = true;
			break;
		}
		
		auto& ContainerIn = f_prop_Container(box);


		for (; i < num; ++i) {
			auto* socket = 节点->f_get输入插座(i);
			std::wstring t;
			S_Props Prop = {};

			//auto type = socket->f_getDataType();
			auto type = socket->m_Type;
			if (socket->f_isLink()) {
				std::wstring t = f_插座数值转文本(socket);

				Prop = f_alloc_StrProp(nullptr, socket->m_identifier);
				f_prop_Str(Prop) = t;

			}
			else {
				switch (type) {
				case E_值类型::e_Type_F32:
					Prop = f_alloc_F32Prop((float32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_I8:
					Prop = f_alloc_I8Prop((int8*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_I32:
					Prop = f_alloc_I32Prop((int32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI32:
					Prop = f_alloc_UI32Prop((uint32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI64:
					Prop = f_alloc_UI64Prop((uint64*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec2:
					Prop = f_alloc_Vec2Prop((vec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec2:
					Prop = f_alloc_iVec2Prop((ivec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2:
					Prop = f_alloc_uVec2Prop((uvec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec3:
					Prop = f_alloc_Vec3Prop((vec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec3:
					Prop = f_alloc_iVec3Prop((ivec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec3:
					Prop = f_alloc_uVec3Prop((uvec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec4:
					Prop = f_alloc_Vec4Prop((vec4*)socket->f_getData(0), socket->m_identifier);
					break;

				case E_值类型::e_Type_路径:
					//Prop = ((C_路径插座*)socket)->m_Value;
					Prop = DEF_路径插座(socket)->m_Value;
					goto To_直接添加到容器;
				/*case E_值类型::e_Type_Vec2_Array1D:
					Prop = f_alloc_Vec2Prop(DEF_Vec2_1D插座数据(socket)->data(), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2:
					Prop = f_alloc_uVec2Prop((uvec2*)socket->f_getData(0), socket->m_identifier);
					break;
				;*/
				case E_值类型::e_Type_Bool_1D:
					Prop = f_alloc_BoolProp(&(DEF_取插座Bool_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_F32_1D:
					Prop = f_alloc_F32Prop(&(DEF_F32插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_I32_1D:
					Prop = f_alloc_I32Prop(&(DEF_I32插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI32_1D:
					Prop = f_alloc_UI32Prop(&(DEF_UI32插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec2_1D:
					Prop = f_alloc_Vec2Prop(&(DEF_Vec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec3_1D:
					Prop = f_alloc_Vec3Prop(&(DEF_Vec3插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec4_1D:
					Prop = f_alloc_Vec4Prop(&(DEF_Vec4插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;

				case E_值类型::e_Type_iVec2_1D:
					Prop = f_alloc_iVec2Prop(&(DEF_iVec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec3_1D:
					Prop = f_alloc_iVec3Prop(&(DEF_iVec3插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2_1D:
					Prop = f_alloc_uVec2Prop(&(DEF_uVec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;

				case E_值类型::e_Type_纹理:
					if (socket->f_isLink()) {
						Prop = f_alloc_StrProp(&socket->m_identifier, socket->m_identifier);
					}
					else {
						switch (DEF_纹理插座数据(socket, 0)->m_格式)
						{
						case E_纹理格式::e_tf_RGB8U_U:
						case E_纹理格式::e_tf_RGB8:
						case E_纹理格式::e_tf_RGB8U:
						case E_纹理格式::e_tf_RGB32:
							Prop = f_propaAlloc_RGB(&(DEF_纹理插座数据(socket, 0)->m_默认颜色), socket->m_identifier);
							break;
						case E_纹理格式::e_tf_R32:
							Prop = f_alloc_F32Prop(&(DEF_纹理插座数据(socket, 0)->m_默认颜色.x), socket->m_identifier);
							break;
						default:
							Prop = f_propaAlloc_RGB(&(DEF_纹理插座数据(socket, 0)->m_默认颜色), socket->m_identifier);
							break;
						}
						//Prop = f_propaAlloc_RGB(&(DEF_纹理插座数据(socket)->m_默认颜色), socket->m_identifier);
						//Prop = f_alloc_F32Prop(&(DEF_纹理插座数据(socket)->m_默认颜色.x), socket->m_identifier);
					}
					
					break;
				default:
					Prop = f_alloc_StrProp(&socket->m_identifier, socket->m_identifier);
					break;
				}

				Prop.m_私有 = true;
				Prop.m_值映射类型 = E_属性引用类型::e_引用;
				Prop.m_UI->m_Update = on_插座参数修改更新节点;

			To_直接添加到容器:
				//Prop.m_GPU内存偏移 = socket->m_GPU内存偏移;
				Prop.m_GPU缓存[0] = socket->m_GPU缓存;
			}
			ContainerIn.m_Item.push_back(Prop);
		}
		props.push_back(box);
	}
	



	{
		uint32 i = 0;
		switch (节点->m_Type) {
		case E_节点类型::e_节点Type_组输入:
		//case E_节点类型::e_节点Type_组输出:
		//case E_节点类型::e_节点Type_函数:
		//case E_节点类型::e_节点Type_循环迭代:
		//case E_节点类型::e_节点Type_循环:
		//case E_节点类型::e_节点Type_几何:
			if (节点->m_插座可编辑) {
				box = f_alloc_PropContainer(DEF_输出插座标题);
				++i;
				break;
			}
		default:
			box = f_alloc_PropLayout(DEF_输出插座标题, E_值类型::e_Type_LayoutList);
			break;
		}

		//box = f_alloc_PropLayout(L"输出插座", E_值类型::e_Type_LayoutList);
		auto& ContainerOut = f_prop_Container(box);

		ico_name.clear();
		num = 节点->f_get输出插座Num();
		for (; i < num; ++i) {
			auto* socket = 节点->f_get输出插座(i);
			std::wstring t = f_插座数值转文本(socket);

			ico_name.push_back({ socket->m_identifier + L" : " + t, ""});
		}
		ContainerOut.m_Item.push_back(f_alloc_EnumProp(nullptr, ico_name, L"输出插座"));
		props.push_back(box);
	}
	
	
	return true;
}



